import sys
import os
import shutil
import unittest
from copy import deepcopy
import configparser

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))

from framework.config_parser import ConfigFileParser
from common.benchmark_var import StatusCode


class ConfigParserTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.configparser = ConfigFileParser()
        cls.config_dir = os.path.join(os.path.dirname(__file__), "config")
        cls.output_dir = os.path.join(os.path.dirname(__file__), "output_dir")
        cls._create_config_dir()

    @classmethod
    def tearDownClass(cls) -> None:
        if os.path.isdir(cls.config_dir):
            shutil.rmtree(cls.config_dir)

        if os.path.isdir(cls.output_dir):
            shutil.rmtree(cls.output_dir)

    def setUp(self):
        pass

    def tearDown(self):
        pass

    @classmethod
    def _create_config_dir(cls):
        if not os.path.isdir(cls.config_dir):
            os.mkdir(cls.config_dir)

    def _create_configfile(self, test_file, value):
        if isinstance(value, dict):
            config_creater = configparser.ConfigParser()
            config_creater.optionxform = lambda option: option
            config_creater.read_dict(value)
            with open(test_file, "w") as cfg:
                config_creater.write(cfg)
        else:
            with open(test_file, "w") as cfg:
                cfg.write(value)

    def test_wrong_file(self):
        test_file = os.path.join(self.config_dir, "test1.ini")
        try:
            self.configparser.parse_ini(test_file)
        except SystemExit as e:
            self.assertEqual(e.code, 1)

    def test_empty(self):
        test_file = os.path.abspath(os.path.join(self.config_dir, "test2.ini"))
        value = {}
        self._create_configfile(test_file, value)

        try:
            self.configparser.parse_ini(test_file)
        except SystemExit as e:
            self.assertEqual(e.code, 1)

    def test_parse_general(self):
        test_file = os.path.abspath(os.path.join(self.config_dir, "test3.ini"))
        value = {
            "general": {
                "action": "standard",
                "test_target": "ServerSuite1,ServerSuite2",
                "iterations": 1,
                "report": "all,pdf"
            }
        }
        self._create_configfile(test_file, value)
        options = self.configparser.parse_ini(test_file)
        expect_general = {
                "action": "standard",
                "test_target": ["ServerSuite1", "ServerSuite2"],
                "iterations": 1,
                "report": ["all", "pdf"]
        }
        self.assertEqual(options["general"], expect_general)

        # test abnormal general params & values
        test_file = os.path.abspath(os.path.join(self.config_dir, "test3.ini"))
        value = {
            "general": {
                "action": "standard",
                "test_target": "ServerSuite1,ServerSuite2",
                "iterations": 1,
                "unknown_key": "unknown_value"
            }
        }
        self._create_configfile(test_file, value)

        try:
            self.configparser.parse_ini(test_file)
        except SystemExit as e:
            self.assertEqual(e.code, 1)

    def test_parse_namespace(self):
        test_file = os.path.abspath(os.path.join(self.config_dir, "test4.ini"))

        value = {
            "general": {
                "action": "standard",
                "test_target": "ServerSuite1,ServerSuite2",
                "iterations": 1
            },
            "ServerSuite.CPUSuite.example_test1": {
                "CFLAGS": "-Ofast"
            }
        }
        self._create_configfile(test_file, value)
        options = self.configparser.parse_ini(test_file)

        expect_namespace = {"CFLAGS": "-Ofast"}
        self.assertEqual(options["ServerSuite.CPUSuite.example_test1"], expect_namespace)

    def test_comment(self):
        test_file = os.path.abspath(os.path.join(self.config_dir, "test5.ini"))
        value = """
        [general]
        action = standard
        iterations = 1
        test_target = ServerSuite1
        taskset = 1-3

        [ServerSuite.CPUSuite.example_test1]
        CFLAGS = -Ofast
        """
        self._create_configfile(test_file, value)
        options = self.configparser.parse_ini(test_file)

        expect_general = {
            "action": "standard",
            "iterations": 1,
            "taskset": [1, 2, 3],
            "test_target": ["ServerSuite1"]
        }
        self.assertEqual(options["general"], expect_general)

        test_file = os.path.abspath(os.path.join(self.config_dir, "test5.ini"))
        value = """
                [general]
                action = standard
                # iterations = 1
                test_target = ServerSuite1
                # taskset = 1-3

                [ServerSuite.CPUSuite.example_test1]
                CFLAGS = -Ofast
                """
        self._create_configfile(test_file, value)
        options = self.configparser.parse_ini(test_file)

        expect_general = {
            "action": "standard",
            "test_target": ["ServerSuite1"]
        }
        self.assertEqual(options["general"], expect_general)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(ConfigParserTestCase)
    unittest.TextTestRunner(verbosity=2).run(suite)


